(function(factory) {
	if (typeof define === "function" && define.amd) {
		// AMD. Register as an anonymous module.
		define(["HteOS/app/Group","HteOS/app/App","HteOS/API"], factory);
	} else {
		// Browser globals
		factory();
	}
}(function() {
	/**
	 * <p>HteOS的应用管理器，所有应用在创建之后都需要在管理器中注册，应用管理器存储了所有应用的实例，并维护了应用和应用组之间的管理</p>
	 * <p>并且应用管理器负责与与服务器之间的交互，例如用于拖动了磁贴的位置，管理器会将排序后的布局保存到数据库中，应用管理器同时向其他组件提供获取、操作应用的方法，例如：如果通过应用ID获取应用：</p>
	 *通过ID获取应用	   
	 * 
	 *	   var app = HteOS.app.AppManager.get("appId");
	 *
	 *通过编码获取应用
	 *
	 * 	   var app = HteOS.app.AppManager.getByKey("appCode");
	 *
	 * @class HteOS.app.AppManager 
	 * @singleton
	 */
	HteOS.app.AppManager = {

		/**
		 * 用于存储所有的应用实例
		 *
		 * @property
		 */
		apps: {},

		/**
		 * 用于存储所有的应用的编码
		 *
		 * @property
		 */
		keys: {},
		
		/**
		 * 存储了所有应用分组，以及应用与分组之间的管理
		 * @property
		 * **/
		groups : {},
		

		/**
		 * 初始化应用管理器，在这个方法中首先监听所有跟后台发生交互的事件，用于在触犯事件之后与服务器进行通讯，在这个方法监听了以下事件：
		 * - hte.tile.move 用户拖拽后磁贴后将用户改变的布局保存到数据库中
		 * - hte.metro.hook 用户将磁贴拖拽到新的分组中，管理器向服务器发送创建新组的请求，并将新创建的分组信息返回
		 * - hte.group.destroy 用户将磁贴中拖出时，如果该分组中没有任何应用，系统将会自动的将改分组销毁，在触发该事件时管理器向服务器发送删除分组请求，保证前后台数据的一致性
		 */
		init: function() {
			$(".hte-preloader-text").text("正在加载应用...");

			// 监听磁贴排序事件
			HteOS.EventManager.on("hte.tile.move", this.move,this);
			
			//监听拖动创建新分组的事件
			//HteOS.EventManager.on("hte.metro.hook",this.hook,this);
			
			//监听分组销毁事件
			HteOS.EventManager.on("hte.group.destroy",this.destroyGroup,this);
			
			HteOS.EventManager.on("hte.group.sort",this.sortGroup,this);
			
			HteOS.EventManager.on("hte.group.rename",this.renameGroup,this);
			
			HteOS.EventManager.on("hte.group.apps.change",this.saveTileIndex,this);

			HteOS.EventManager.on("hte.app.resize",this.resize,this);
			
			HteOS.EventManager.on("hte.desktop.shortcut.index.change",this.saveShortcutIndex,this);
			//加载应用
			this.load();
		},
		
		/**
		 * @private
		 * <p>获取当前用户安装的应用，如果没有登录则返回全部默认应用</p>
		 * <p>获取应用列表的URL在HteOS.API.APP_LIST中定义了，如果需要重写改内容。可以在监听hte-beforestart事件，重写改URL</p>
		 * <p>在获取应用列表之后，管理器会将所有的应用实例化并存储起来，作为整个桌面的数据源，并触发hte.app.load事件</p>
		 */
		load: function() {
			var me = this;
			
			$.getJSON(HteOS.API.APP_LIST, function(data) {
				
				var groups= data.groups
				//对分组进行排序
				groups.sort(function(a,b){
					if(a.index > b.index){
						return 1;
					}
					return -1;
				});
				
				//创建分组
				for(var i = 0; i < groups.length; i++){
					me.createGroup(groups[i]);
				}
				
				var apps = data.apps;
				//创建应用
				for (var i = 0; i < apps.length; i++) {
					var options = apps[i];
					var group = me.getGroup(options.group);
					if(group){
						var app = me.createApp(options);
						group.add(app);
					}
				}
				
				/**
				 * 所有应用加载完毕并且全部实例化
				 * @event hte-app-load
				 * */
				HteOS.EventManager.trigger("hte.apps.instantiated");
			});
		},
		
		/**
		 * 根据获取的配置实例化应用
		 * @param {Object} options 应用配置
		 * @return {HteOS.app.App} app 创建好的应用
		 * */
		createApp : function(options){
			//var group = this.getGroup(options.group);
			//if(group){
				var app = new HteOS.app.App(options);
				//group.add(app);
				return app;
			//}
		},
		
		/**
		 * 根据配置实例化分组
		 * @param {Object} options 分组配置
		 * @return {HteOS.app.Group} group 创建好的分组
		 * */
		createGroup : function(options){
			var group = new HteOS.app.Group(options);
			this.groups[group.id] = group;
			return group;
		},
		
		/**
		 * 根据ID获取分组
		 * @param {String} id 分组ID
		 * @return {HteOS.app.Group} group
		 * */
		getGroup : function(id){
			return this.groups[id];
		},
		
		/**
		 * 根据ID删除本地分组
		 * @param {HteOS.app.Group} group;
		 * */
		removeGroup : function(group){
			delete this.groups[group.id];
		},
		
		
		/**
		 * 向服务器发送请求，销毁分组。请求的URL为：HteOS.API.GROUP_DESTROY
		 * @param {HteOS.app.Group} group;
		 * */
		renameGroup : function(group){
			var me = this;
			$.ajax({
				url: HteOS.API.GROUP_RENAME,
				method: HteOS.API.METHOD,
				data : {
					group : group.id,
					name : group.name
				},
				success: function(data) {
					if (!data.success) {
						HteOS.Notification.show("", "应用消息",
							data.message, true)
					}
				},
				error: function() {
					HteOS.Notification.show("", "应用消息",
						"操作太快了，磁贴位置保存失败", true)
				}
			});
		},
		
		/**
		 * 向服务器发送请求，销毁分组。请求的URL为：HteOS.API.GROUP_DESTROY
		 * @param {HteOS.app.Group} group;
		 * */
		destroyGroup : function(group){
			var me = this;
			$.ajax({
				url: HteOS.API.GROUP_DESTROY,
				method: HteOS.API.METHOD,
				data : {
					group : group.id
				},
				success: function(data) {
					if (!data.success) {
						HteOS.Notification.show("", "应用消息",
							data.message, true)
					}else{
						me.removeGroup(group);
					}
				},
				error: function() {
					HteOS.Notification.show("", "应用消息",
						"操作太快了，磁贴位置保存失败", true)
				}
			});
		},
		
		/**
		 * 钩子方法，这个是磁贴拖动到钩子组件中，释放后向后台发送请求创建分组
		 * 后台返回创建的分组信息，根据返回的信息创建分组，并且将该磁贴的应用添加到新的分组当中
		 * @param {Object} tile;
		 * */
		addToNewGroup : function(app){
			var me = this;
			$.ajax({
				url: HteOS.API.GROUP_CREATE,
				method: HteOS.API.METHOD
			}).success(function(data) {
				if (!data.success) {
					HteOS.Notification.show("", "应用消息",
						data.message, true)
				}else{
					var group = me.createGroup(data.group);
					/**
					 * 后台返回消息之后创建分组，并触发事件
					 *@event hte-group-create
					 * @param {HteOS.app.Group}
					 */
					HteOS.EventManager.trigger("hte.group.create",group);
					group.add(app);
				}
			}).error(function() {
				HteOS.Notification.show("", "应用消息",
					"操作太快了，磁贴位置保存失败", true)
			});
		},
		
		/**
		 * 将指定的分组中所有应用的位置发送到后台
		 * @param {HteOS.app.Group} group;
		 */
		saveTileIndex: function(group) {
			var index = 1,
				indexes = "",apps = group.apps;
			for(var appId in apps){
				var app = apps[appId];
				if (indexes.length > 0) {
					indexes += ";";
				}
				indexes += appId + "," + app.indexOf();
			};
			if (indexes.length > 0) {
				$.ajax({
					url: HteOS.API.APP_SORT,
					method: HteOS.API.METHOD,
					data: {
						indexes: indexes,
						group : group.id
					}
				}).success(function(data) {
					if (!data.success) {
						HteOS.Notification.show("", "应用消息",
							data.message, true)
					}
				}).error(function() {
					HteOS.Notification.show("", "应用消息",
						"操作太快了，磁贴位置保存失败", true)
				});
			}
		},
		
		/**
		 * 将指定的分组中所有应用的位置发送到后台
		 * @param {HteOS.app.Group} group;
		 */
		saveShortcutIndex: function(changes) {
			var indexes = "";
			for(var app in changes){
				var index = changes[app];
				if (indexes.length > 0) {
					indexes += ";";
				}
				indexes += app + "," + index;
			};
			if (indexes.length > 0) {
				$.ajax({
					url: HteOS.API.SAVE_SHORTCUT_INDEX,
					method: HteOS.API.METHOD,
					data: {
						indexes: indexes
					}
				}).success(function(data) {
					if (!data.success) {
						HteOS.Notification.show("", "应用消息",
							data.message, true)
					}
				}).error(function() {
					HteOS.Notification.show("", "应用消息",
						"操作太快了，磁贴位置保存失败", true)
				});
			}
		},
		
		/**
		 * 保存桌面中所有分组的排序信息
		 */
		sortGroup: function() {
			var index = 1,
				indexes = "";
			for(var id in this.groups){
				var group = this.groups[id];
				if (indexes.length > 0) {
					indexes += ";";
				}
				indexes += group.id + "," + group.index;
				//设置APP的下表
				index++;
			}
			if (indexes.length > 0) {
				$.ajax({
					url: HteOS.API.GROUP_SORT,
					method: HteOS.API.METHOD,
					data: {
						indexes: indexes
					}
				}).success(function(data) {
					if (!data.success) {
						HteOS.Notification.show("", "应用消息",
							data.message, true)
					}
				}).error(function() {
					HteOS.Notification.show("", "应用消息",
						"操作太快了，分组位置保存失败", true)
				});
				
			}
		},
		
		/**
		 * 向后台发送调正应用大小
		 * @param {HteOS.app.App} app
		 */
		resize : function(app){
			$.ajax({
				url: HteOS.API.APP_RESIZE,
				method: HteOS.API.METHOD,
				data: {
					id: app.id,
					size : app.size
				}
			}).success(function(data) {
				if (!data.success) {
					HteOS.Notification.show("", "应用消息", "调整应用大小失败:" + data.message, true);
				}
			}).error(function() {
				HteOS.Notification.show("", "应用消息", "调整应用大小失败", true)
			});
		},
		
		/**
		 * 向后台发送显示应用的请求，请求成功后，将指定的应用显示出来，更新磁贴状态
		 * @param {HteOS.app.App} app
		 */
		show: function(app) {
			if (!app) {
				return ;
			}
			$.ajax({
				url: HteOS.API.APP_SHOW,
				method: HteOS.API.METHOD,
				data: {
					id: app.id
				}
			}).success(function(data) {
				if (data.success) {
					app.show();
				} else {
					HteOS.Notification.show("", "应用消息", "显示应用[" + app.name + "]失败:" + data.message, true);
				}
			}).error(function() {
				HteOS.Notification.show("", "应用消息", "显示应用[" + app.name + "]失败", true)
			});
		},

		/**
		 * 向后台发送隐藏应用的请求，请求成功后，将指定的应用隐藏，更新磁贴状态
		 * @param {HteOS.app.App} app
		 */
		hide: function(app) {
			if (app) {
				$.ajax({
					url: HteOS.API.APP_HIDE,
					method: HteOS.API.METHOD,
					data: {
						id: app.id
					},
					success: function(data) {
						if (data.success) {
							app.hide();
						} else {
							HteOS.Notification.show("", "应用消息", "隐藏应用[" + app.name + "]失败:" + data.message, true);
						}
					},
					error: function() {
						HteOS.Notification.show("", "应用消息", "隐藏应用[" + app.name + "]失败", true)
					}
				});
			}
		},

		/**
		 * 注册应用
		 * @param {HteOS.app.App} app
		 */
		register: function(app) {
			this.apps[app.id] = app;
			if (app.code) {
				this.keys[app.code] = app.id;
			}
		},

		/**
		 * 注销应用
		 * @param {HteOS.app.App} app
		 */
		unregister: function(app) {
			var group = this.groups[app.group];
			if(group){
				delete group[app.id]
			}
			delete this.apps[app.id];
			if(this.keys[app.code]){
				delete this.keys[app.code];
			}
		},

		/**
		 * 根据应用编码获取应用
		 * @param {String}  key
		 * @return {HteOS.app.Appp} app
		 */
		getByKey: function(key) {
			if (this.keys[key]) {
				return this.get(this.keys[key]);
			}
		},

		/**
		 * 根据ID获取应用实例
		 * @param {String} id
		 * @return {HteOS.app.Appp} app
		 */
		get: function(id) {
			return this.apps[id];
		},
		
		getByEl : function(el){
			return this.get(el.data("appId"));
		},

		/**
		 * 安装应用之后显示在桌面中
		 * @param {String} id
		 */
		install: function(id) {
			var me = this;
			$.getJSON(HteOS.API.APP_GET, {
				id: id
			},doInstall);
			function doInstall(options){
				var group = me.getGroup(options.group);
				if(group){
					var app = me.createApp(options);
					/**
					 *安装成功之后触发事件
					 * @event hte-app-install
					 * @param {HteOS.app.App}
					 */
					HteOS.EventManager.trigger("hte.app.install",app);
					group.add(app);
				}
			}
		},

		/**
		 * 根据DOM选中对应的app
		 * @param {Object}  tile
		 */
		select: function(tile) {
			var app = this.getByEl(tile);
			if (app) {
				tile.addClass("selected");
			}
			return app;
		},

		/**
		 * 卸载指定的应用，向后台发送卸载应用的请求
		 * @param {HteOS.app.App} app
		 */
		uninstall: function(app) {
			if (app) {
				HteOS.Messager.confirm("HteOS提示","确定要卸载应用["+ app.name +"]么？",function(btn){
					if(btn == 'yes'){
						doUninstall();
					}
				});
			}
			function doUninstall(){
				$.ajax({
					url: HteOS.API.APP_UNINSTALL,
					method : HteOS.API.METHOD,
					data: {
						id: app.id
					},
					success: function(data) {
						if (data.success) {
							app.uninstall();
							// TODO 刷新应用的位置
							HteOS.Notification.show("", "应用消息", "应用[" + app.name + "]卸载成功", true);
						} else {
							HteOS.Notification.show("", "应用消息", "应用[" + app.name + "]卸载失败：" + data.message, true);
						}
					},
					error: function() {
						HteOS.Notification.show("", "应用消息", "应用[" + app.name + "]卸载失败，请稍候再试",
							true);
					}
				});
			
			}
		},
		
		/**
		 * 将指定的应用固定到快速启动栏，向后台发送固定请求
		 * @param {HteOS.app.App} app
		 */
		pink: function(app) {
			if (app) {
				$.ajax({
					url : HteOS.API.APP_PINK,
					method : HteOS.API.METHOD,
					data: {
						id: app.id
					},
					success: function(data) {
						if (data.success) {
							app.pink();
							// TODO 刷新应用的位置
							HteOS.Notification.show("", "应用消息", "应用[" + app.name + "]添加到快速启动成功",
								true);
						} else {
							HteOS.Notification.show("", "应用消息", "应用[" + app.name + "]添加到快速启动失败：" + data.message, true);
						}
					},
					error: function() {
						HteOS.Notification.show("", "应用消息",
							"应用[" + app.name + "]添加到快速启动失败，请稍候再试",
							true);
					}
				});
			}
		},

		/**
		 * 将指定的应用移除出快速启动栏，向后台发送移除请求
		 * @param {HteOS.app.App} app
		 */
		unpink: function(app) {
			if (app) {
				$.ajax({
					url: HteOS.API.APP_UNPINK,
					method : HteOS.API.METHOD,
					data: {
						id: app.id
					},
					success: function(data) {
						if (data.success) {
							app.clearQuick();
							// TODO 刷新应用的位置
							HteOS.Notification.show("", "应用消息", "快速启动[" + app.name + "]删除成功", true);
						} else {
							HteOS.Notification.show("", "应用消息", "快速启动[" + app.name + "]删除失败：" + data.message, true);
						}
					},
					error: function() {
						HteOS.Notification.show("", "应用消息", "快速启动[" + app.name + "]删除失败，请稍候再试",
							true);
					}
				});
			}
		}
	};
	/**
	 * @deprecated
	 * @see {HteOS.app.AppManager.pink}
	 * 将应用添加到快速启动栏
	 * */
	HteOS.app.AppManager.setQuick = HteOS.app.AppManager.pink;
	/**
	 * @deprecated
	 * @see {HteOS.app.AppManager.unpink}
	 * 将应用移出快速启动栏
	 * */
	HteOS.app.AppManager.clearQuick = HteOS.app.AppManager.unpink;
	HteOS.AppManager = HteOS.app.AppManager;
}));